﻿
#pragma once

#include "ECommon.h"
#include <Windows.h>

// 图形渲染底层分两种实现, 一种为GDI一种为GDI+, 当需要使用GDI+时取消下面的注释重新编译即可
// 但是GDI+的效率差GDI很多, 虽然他们使用的方法相同
//#define GRAPHICS_DGIPLAS 1

#ifdef GRAPHICS_DGIPLAS
	#include <GdiPlus.h>
#endif

namespace Base3D
{
	/*
		用于底层绘制图像, 实现像素级别的绘制功能, 底层实现使用GDI+
		
		
		调用方法
		// 初始化GDI+
		InitDraw()

		HDC          hdc;
		PAINTSTRUCT  ps;

		// 循环绘制
		while(1)
		{
			// 获得hdc
			hdc = BeginPaint(hWnd, &ps);
			
			// 清楚缓冲区
			ClearBuffer()
			// 绘制操作
			....
			DrawLine(...)
			....
			// 翻转缓冲区
			FillBuffer(hdc)

			//释放hdc
			EndPaint(hWnd, &ps);
		}

		// 结束 释放GDI+
		ShutdownDraw()
	*/

	extern HINSTANCE GHInstance;

	// 图片封装, 由于图片使用的GDI+的图片类, 
	// 所以这里对他进行封装, 将平台相关的东西隐藏
	class EBitmap
	{
	public:
		EInt width, height;

		EBitmap(const EString &filename);
		~EBitmap();

		inline EString getName() const { return name; }
		inline bool isValid() const { return valid;}
		EColor getPixel(EInt x, EInt y);
		inline EInt getHeight() const { return height;}
		inline EInt getWidth() const { return width;}

	private:
		EString					name;

#ifdef GRAPHICS_DGIPLAS
		Gdiplus::Bitmap			*bitmap;
		Gdiplus::BitmapData		*bitmapData;

	public:
		UINT					*pixels;
#else
		HBITMAP					hBitmap;
		BITMAP					bitmap;
		HDC						bitmapHDC;

	public:
		EColor					*pixels;		
#endif
		EInt					pitch;

		EBool					valid;
	};


	class EGraphics
	{
	public:

		// 初始化绘图系统
		static bool initGraphics(HINSTANCE hinstance);
		// 关闭绘图系统
		static void shutdownGraphics();

		// 检测z值, 返回true则表示通过, 可以调用setPixel
		static EBool checkZ(EInt x, EInt y, EFloat z);
		static void setPixel(EInt x, EInt y, /*EFloat z, */const EColor &c);
		static EColor getPixel(EInt x, EInt y);
		// 在当前缓冲区内绘制一条线
		static void drawLine(EInt x0, EInt y0, EInt x1, EInt y1, const EColor &c);
		static void drawString(const EString &str, EInt x, EInt y, const EColor &c = EColor(255, 255, 255));
		static void fillTriangle(EInt x0, EInt y0, EInt x1, EInt y1, EInt x2, EInt y2, 
							const EColor &c = EColor(255, 255, 255));

		static void enableSmoothingMode(EBool enable);

		// 清空当前缓冲区, 并将其颜色设置为黑色
		static void clearBuffer(const EColor &c = EColor());
		// 将已经绘制好的缓冲区递交给Graphics在屏幕上绘制, 并将当前缓冲区设置为另一个缓冲区
		static void fillBuffer(HDC hdc);

		static EInt getScreenWidth() { return SCREEN_WIDTH; }
		static EInt getScreenHeight() { return SCREEN_HEIGHT; }

	private:
#ifdef	GRAPHICS_DGIPLAS
		static Gdiplus::GdiplusStartupInput		GDiplusStartupInput;
		static ULONG_PTR						GDiplusToken;

		// 主缓冲区和后缓冲区
		static Gdiplus::Bitmap					*GCurrentBuffer;
		static Gdiplus::Graphics				*GCurrentGraphics;

		static Gdiplus::Font					*GFont;

		static Gdiplus::BitmapData				*GBitmapData;
		static UINT								*GPixels;
#else
		// 保存变量
		static HBITMAP							GBufferedHandle;
		static HDC								GBufferedHDC;
		static HBRUSH							GBgBrush;
		static HPEN								GPen;
		static HINSTANCE						GInstance;

		static BYTE								*GData;
		static EInt								GPitch;

		static DIBSECTION						GDIBSection;
	
		static RECT								GBufferSize;
#endif
		static EFloat							*GZBuffer;
	};
}
